#include <unistd.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <stdio.h>

#include "devices.h"
#include "console.h"
#include "clock.h"
#include "intr.h"

#define PGSIZE        4096
#define UM_STUB_CODE  0x100000
#define UM_STUB_DATA  (UM_STUB_CODE + PGSIZE)
#define UM_SHARED_MEM (UM_STUB_DATA + PGSIZE)

struct _device_common *device_common;

static int shmid;

/**
 * Finish common initializing tasks which are needed for both processes.
 */
void
device_init_common (void)
{
	/* Apply for the shared memory */
	shmid = shmget (IPC_PRIVATE, sizeof(struct _device_common), IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
	device_common = shmat (shmid, (void*)UM_SHARED_MEM, 0);
	if ((int)device_common != UM_SHARED_MEM) {
		_exit (-1);
	}
	
	cons_init ();
	intr_init ();
}


/**
 * Carry out tracing-process specific initializing work.
 * @param cpid pid of the child process.
 */
void
device_init_tracing_process (int cpid)
{
	device_common->cpid = cpid;
	
	/* Initialize shared memory. */
	device_common->cons_front = device_common->cons_end = 0;
}


/**
 * Carry out child-process specific initializing work
 */
void
device_init_child_process (void)
{
	/* 'setitimer' sets the timer of the calling process.
	 *     so clock must be initialized in child process.
	 */
	clock_init ();
}


/**
 * Finalize devices if needed.
 */
void
device_dtor (void)
{
	/* Destroy the shared memory */
	shmctl (shmid, IPC_RMID, 0);
	
	cons_dtor ();
}
